#include "stdafx.h"

#include "Business/CustomerPosition.h"

#include "Business/Dealing.h"
#include "Utils/Logger.h"


void CustomerPosition::DoOnDealing(Dealing const& dealing)
{
	UNREFERENCED_PARAMETER(dealing);
}

void CustomerPosition::DoOnTrade(Trade const& trade)
{
	PositionKey key(trade.GetContract(),GetDirection(trade.GetDealing()),GetOperation(trade.GetDealing()));
	PositionValue& value = m_positions[key];

	if (trade.GetDealing().IsOpenOrder())
	{
		value.Plus(PositionValue(trade.GetDealPrice(),trade.GetDealQuantity()));
	}
	else
	{
		value.Sub(trade.GetDealQuantity());
	}
}

void CustomerPosition::Plus(PositionKey const& key, PositionValue const& value)
{
	m_positions[key].Plus(value);
}

PositionValue const& CustomerPosition::Get(PositionKey const& key) const
{
	std::map<PositionKey,PositionValue>::const_iterator iter = m_positions.find(key);
	if (iter == m_positions.end())
	{
		static PositionValue s_emptyPosition;
		return s_emptyPosition;
	}
	return iter->second;
}

PositionValue const& CustomerPosition::Get(Dealing const& dealing) const
{
	PositionKey key(dealing.GetContract(),GetDirection(dealing),GetOperation(dealing));
	return Get(key);
}

Operation::TYPE CustomerPosition::GetOperation(Dealing const& dealing) const
{
	return dealing.GetOperation() == Operation::OFFSET ? 
		Operation::OFFSET : Operation::OFFSET_TODAY ;
}

Direction::TYPE CustomerPosition::GetDirection(Dealing const& dealing) const 
{
	return dealing.IsOpenOrder() ? dealing.GetDirection() : GetNegative(dealing.GetDirection());
}

PositionValue& PositionValue::Plus(PositionValue const& other)
{
	double total = GetTotal() + other.GetTotal();
	m_quantity += other.GetQuantity();
	m_price = total / m_quantity;
	return *this;
}

PositionValue& PositionValue::Sub(int quantity)
{
	if (quantity > m_quantity)
	{
		LightLogger::Fatal("PositionValue Sub Fatal:");		
		return *this;
	}
	m_quantity -= quantity;
	if (m_quantity == 0)
	{
		m_price = 0.00;
	}
	return *this;
}

PositionValue& PositionValue::Sub(PositionValue const& other)
{
	return Sub(other.GetQuantity());
}
